home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
151-175
/
disk_175
/
virusx
/
virusx.c
< prev
next >
Wrap
Text File
|
1992-05-06
|
55KB
|
1,653 lines
/************************************************************************/
/* */
/* */
/* VirusX */
/* */
/* by Steve Tibbett */
/* */
/* */
/* Please - if you find a new virus, Send me a copy! */
/* (And warn me it's on the disk!). I want to keep */
/* this program current. (Feel free to put something */
/* neat on the disk also!) */
/* */
/* This version of VirusX is my first done with the Lattice 5.0 */
/* compiler. The Lattice compiler, with the help of John Toebes, */
/* gave me an executable almost 4K smaller than the best I could */
/* get out of Manx. Reason enough for me to switch! */
/* */
/* The Makefile included in the "source.zoo" file you should have */
/* gotten in the VirusX.Zoo file this came from, is set up for the */
/* MANX Make Utility. Switching to Lattice's LMK should be easy, */
/* but I've had no reason to. The important thing is the command */
/* line switches and the BLINK command line. */
/* */
/* Thanks to John Toebes for a lot of help getting it going, and */
/* thanks to Dan James for providing the routine down at the bottom */
/* that actually takes the IRQ Virus out of executable files. */
/* */
/************************************************************************/
/* */
/* History: */
/* -------- */
/* April '88 or so: V1.0 written and released. */
/* A few days later: V1.01 released. V1.0 wrote garbage to the */
/* disk if it was write protected then fixed. */
/* 27-March-88: V1.2 released. V1.2's purpose in life was */
/* to deal with the Byte Bandit virus. */
/* (Actually, it's well after midnight - make */
/* that March 28th. :) */
/* 28-March-88: Oops, V1.2 was 3K or so bigger than it needed */
/* to be. Fix it, release v1.21. */
/* 15-June-88: V1.3, V1.2 cleaned up and made smaller. */
/* 8-July-88: V1.4. Revenge virus checking, Viewbooting, */
/* check for SCA in RAM, more cleaning up. */
/* 24-July-88: V1.5, only change was the addition of the */
/* Byte Warrior virus. */
/* 1-Aug-88: V1.6 (busy week), Dan Mosedale sent me the */
/* Northstar Virus. Nuked it. */
/* 18-Aug-88: V1.7 - after 2 weeks off, got the Obelisk */
/* Softworks crew virus. */
/* a few days later: V1.71, can't remember why. */
/* September Sometime: Biggest mistake of my life, released V2.0. */
/* 3 days later: Bigger mistake: Released V2.01 - which was */
/* 2.0 with another bug added. Argh. */
/* 6-Nov-88: Finally got some time to clean things up, */
/* check out the startup code bugs, clean up the */
/* docs and source, and release V2.1. There */
/* haven't been any new viruses in about a month */
/* now, but I hear one or two are on the way. */
/* 31-Dec-88: Got the IRQ virus yesterday. Neat one! */
/* Releasing V3.0 tonite or tomorrow to handle */
/* it. See description below. */
/* 04-Jan-89: Got 2 new viruses, released 3.1. */
/* */
/************************************************************************/
/* */
/* Viruses Dealt With: */
/* ------------------- */
/* */
/* SCA - The SCA is the simplest virus to deal with, */
/* as it's not actually DOING anything except */
/* hiding in memory, until you reboot. */
/* We just look at CoolCapture and fix it to get */
/* it out of RAM. */
/* */
/* Byte Bandit - The Byte Bandit virus takes the DoIO() vector */
/* and redirects it through itself. Thus, any */
/* attempt to read or write the boot block (ie, */
/* AmigaDOS trying to figure out what kind of */
/* disk it is) results in the BB writing itself */
/* onto that disk. VirusX couldn't just rewrite */
/* the boot block, we have to get him out of RAM */
/* first. This virus also has an interrupt that */
/* crashes the machine every 5 minutes or so */
/* after it's infected a few of your disks. Ow. */
/* It stays in memory not via the Capture */
/* vectors, but by a Resident module. */
/* */
/* Revenge - Basically, a Byte Bandit clone except it will */
/* bring up an obscene pointer a few minutes */
/* after you reboot. We treat it much like the */
/* byte bandit. */
/* */
/* Byte Warrior - Jumps right into 1.2 Kickstart. Won't work */
/* under 1.3. Hangs around via Resident struct, */
/* doesn't do any damage. */
/* */
/* North Star - Like SCA, hangs around via CoolCapture, */
/* killing CoolCapture kills the North Star. */
/* */
/* Obelisk Softworks Crew */
/* - Hangs around via CoolCapture, also */
/* watches reads of DoIO() (but doesn't */
/* infect EVERY disk - onlyt ones you boot */
/* off of) */
/* */
/* IRQ - This is the FIRST Non-Bootblock Virus. */
/* It copies itself from place to place via the */
/* first executable program found in your */
/* startup-sequence. It SetFunction's */
/* OldOpenLibrary(), has a KickTagPtr, */
/* and lives in the first hunk of an */
/* infected program. */
/* THANKS! to Gary Duncan and Henrik Clausen for */
/* being the first to send this one to me! */
/* */
/* Pentagon Circle - This one looks at the DoIO vector, and has */
/* a CoolCapture vector. It will write itself */
/* over any virus inserted, but not onto */
/* anything else. (Neat idea!). No danger, */
/* easy to eliminate. Holding left button */
/* while booting with this one shows different */
/* screen colour, but doesn't get rid of it. */
/* Thanks to Bill at CMI (CMI*BILL on Plink) */
/* for sending me this one! */
/* */
/* SystemZ Virus Protector */
/* - This is another 'virus protector' that */
/* can write itself to disks. Anything that */
/* spreads itself, under any name, is a */
/* virus. Doesn't do anything except during */
/* a reboot, then examines disks and writes */
/* over viruses. Again, from CMI*BILL. */
/* */
/* Thanks also to Robb Walton for being the first to send one of the */
/* other ones, (but I can't remember which one anymore... 8-( ) */
/************************************************************************/
/* */
/* Notes on making VirusX yourself: The source is included mainly */
/* for your perusal, not so that you can modify it and redistribute */
/* it. I've modified Manx's _main.c module to make the detach */
/* from the initial CLI work properly. I can't redistribute this */
/* module since it's copyright manx, so here's VirusX without it. */
/* It will compile and run, but if you run it from WB, it won't quit. */
/* The version I've supplied should do everything just fine. */
/* */
/************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <devices/bootblock.h>
#include <devices/trackdisk.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <pragmas/all.h>
#include <proto/all.h>
#include <String.h>
#include "virusx.i"
/* Latticeisms */
void MemCleanup() {}
/********************************************************************/
/* These string constants are used in multiple places, and thus */
/* save bytes by having only one copy of them. */
/********************************************************************/
char TITLETEXT[] = "VirusX 3.10 by Steve Tibbett";
char TDName[] = "trackdisk.device";
char copystring[] = "(Copy Count on this disk: %d)";
char ITBodyText[80];
char VN_OBELISK[] = "Obelisk";
char VN_NORTHSTAR[] = "North Star";
char VN_SCA[] = "SCA";
char VN_BYTEBANDIT[] = "Byte Bandit";
char VN_BYTEWARRIOR[] = "Byte Warrior";
char VN_REVENGE[] = "Revenge";
char VN_IRQ[] = "IRQ";
char VN_PENTAGON[] = "Pentagon Circle";
char VN_SYSTEMZ[] = "SystemZ";
char CaptureStr[] = "Capture is pointing at $";
char text[] = "DF6: Boot Sectors";
#define WIN_SIZE 122L
/* Release Date of this version of VirusX */
char date[] = "January 4, 1988";
/********************************************************************/
/* These counters are for the Info window, one for each virus. */
/********************************************************************/
int ObeliskCount;
int NorthStarCount;
int SCACount;
int ByteBanditCount;
int ByteWarriorCount;
int RevengeCount;
int IRQFound;
int PentagonCount;
int SystemZCount;
/*******************************************************************/
/* Miscellaneous variables. */
/*******************************************************************/
long ChangeCount[4]; /* TD_CHANGECOUNT for 4 drives */
long LastSum; /* Used in the checksumming */
long error; /* sort of a temporary variable */
char WindowBig; /* TRUE if the window is big */
struct Port *diskport; /* trackdisk's port. */
struct IOStdReq *diskreq; /* trackdisk's IOStdReq */
int DisksChecked, DisksInstalled; /* for title bar info */
long VirusBase; /* ick, whatta name! */
char FromCLI; /* True if run from CLI */
struct Process *Process;
struct IntuitionBase *IntuitionBase; /* For Library Bindings */
struct GfxBase *GfxBase;
struct Window *Window;
struct IntuiMessage *Message;
struct ExecBase *ExecBase;
struct IOStdReq *TimerReq;
struct MsgPort *TimerPort;
static long fp;
char Keepgoing; /* A flag. It's false when we want out. */
long x, y, i; /* Left over from my using Basic */
char flag; /* Another flag. Lets start our own country. */
LONG thing1, thing2;
struct NewWindow NewWindow =
{
128,0, 309,10, 0,1,
DISKINSERTED | CLOSEWINDOW | VANILLAKEY | NEWSIZE | MOUSEBUTTONS, /* IDCMP Flagz */
WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
NULL, NULL,TITLETEXT,
NULL,NULL,0,0,0,0,WBENCHSCREEN,
};
struct RastPort *RP;
#define BSIZE 40 /* Ha! I'm not telling what this is! */
/*******************************************************************/
/* diskbuffer is where all disk io goes to. it's 3*512 rather */
/* than 2*512, because I believe one of the viruses watches for */
/* reads of 1024 bytes, so I'm just being safe. */
/*******************************************************************/
UBYTE *diskbuffer;
/************************************************************************/
/* Warning messages. These messages get modified before being */
/* displayed (Unless you DO have a DF9:) */
/************************************************************************/
char TEXTPTR[] = "Danger: The disk in DF9: is";
char NBCTEXT[] = "Danger: The disk in DF9: has"; /* What a waste, eh? */
char CopyText[40];
/*************************************************************************/
/* This is a byte by byte copy of working boot block code. Check it */
/* out if you like. This is what gets written back to the disk when */
/* you ask VirusX to fix a disk. */
/*************************************************************************/
unsigned char bootblock[] = { 'D', 'O', 'S', 0,
0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
0x00, 0x00};
/********************************************************************/
/* My intuition defines. There's lots of 'em - theyre self explan.*/
/********************************************************************/
struct TextAttr TxtAt_Plain =
{
"topaz.font", 8, FS_NORMAL, FPF_ROMFONT
};
/*** Non SCA warning requester IntuiText's ***/
struct IntuiText Body2 =
{
0, 1, JAM2, 20,18, &TxtAt_Plain, "Nonstandard Boot Code!", NULL
};
struct IntuiText Body1 =
{
0,1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2
};
/*- This one says "The disk in DFx: is" -*/
struct IntuiText GenericFirstBody =
{
0,1, JAM2, 20,8,&TxtAt_Plain, (UBYTE *)TEXTPTR, 0
};
/***** Generic IntuiTexts used as of V1.7 ******/
struct IntuiText GenericDiskBody =
{
0,1, JAM2, 20,18, &TxtAt_Plain,ITBodyText, &GenericFirstBody
};
struct IntuiText SCAPos =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL
};
struct IntuiText Repair =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Repair it", NULL
};
struct IntuiText SCANeg =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL
};
/* Special cases (display copy count) */
/***** BBANDIT Requester IntuiText's ******/
struct IntuiText BBDiskbody2 =
{
0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
};
struct IntuiText BBDiskbody =
{
0,1, JAM2, 20,18, &TxtAt_Plain, ITBodyText, &BBDiskbody2
};
/***** Revenge on Disk Requester IntuiText's ******/
struct IntuiText RevDiskbody3 =
{
0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
};
struct IntuiText RevDiskbody =
{
0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3
};
/***** Generic Notice - Removed from Memory ****/
struct IntuiText GRB3 =
{
0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled. See the", NULL
};
struct IntuiText GRB2 =
{
0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &GRB3
};
struct IntuiText GenericRAMBody =
{
0,1, JAM2, 20, 8, &TxtAt_Plain, ITBodyText, &GRB2
};
struct IntuiText BBMPos =
{
0,1, JAM2, 7, 3, &TxtAt_Plain, " Thanks! ", NULL
};
struct IntuiText Mem3 =
{
0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "some other utility is the cause of it.", NULL
};
struct IntuiText Mem2 =
{
0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "This could mean a new Virus is in RAM, or", &Mem3
};
struct IntuiText Mem1 =
{
0,1, JAM2, 20, 8, &TxtAt_Plain, 0 , &Mem2
};
/***** Write Protect Error Requester IntuiText's ******/
struct IntuiText ERRBody2 =
{
0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL
};
struct IntuiText ERRBody =
{
0,1, JAM2, 20,8, &TxtAt_Plain, (UBYTE *)"DISK ERROR: Disk is", &ERRBody2
};
struct IntuiText ERRPos =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL
};
struct IntuiText ERRNeg =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL
};
/***** Rewrite block? Really? ******/
struct IntuiText REWBody3 =
{
0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL
};
struct IntuiText REWBody2 =
{
0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3
};
struct IntuiText REWBody =
{
0,1, JAM2, 20,8, &TxtAt_Plain, (UBYTE *)"Are you sure you want to", &REWBody2
};
struct IntuiText REWPos =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL
};
struct IntuiText REWNeg =
{
0,1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL
};
/*********************Da Beginnin*************************/
void main(argc, argv)
int argc;
char **argv;
{
FromCLI = TRUE;
switch (argc)
{
case 0:
FromCLI = FALSE;
break;
case 3:
NewWindow.LeftEdge = atoi(argv[1]);
NewWindow.TopEdge = atoi(argv[2]);
break;
};
WindowBig = FALSE;
/* Come on, folks, is intuition ever NOT going to be available???? */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
/* Same with GfxBase. If GfxBase is gone, we DESERVE to crash. */
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0);
diskbuffer = AllocMem((long)3*512, (long)MEMF_CHIP|MEMF_CLEAR);
if (diskbuffer == 0)
{
exit(10);
};
/* We use the same port/request through the whole program. Works OK. */
diskport = CreatePort(0L,0L);
diskreq = CreateStdIO(diskport);
Window = OpenWindow(&NewWindow);
if (Window == NULL)
goto Quitter; /* No memory to open little window! */
Process = (struct Process *)FindTask(0L);
Process->pr_ConsoleTask = 0;
RP = Window->RPort;
/* This does some setup stuff, I guess, eh? */
SetUp();
/* Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM. */
CheckMemoryForViruses();
CheckMemoryForIRQVirus();
CheckBlock();
DoLittle(); /* The main loop. Do Little. Ya. */
Quitter:
if (diskport != 0) DeletePort(diskport);
if (diskreq != 0) DeleteStdIO(diskreq);
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
CloseLibrary((struct Library *)ExecBase);
FreeMem(diskbuffer, (long)3*512);
exit(0);
}
/*********************/
DoLittle()
{
register long Code; /* for storing our IntuiMessage stuff */
register long Class;
register char KG2; /* KeepGoing 2. Another booleean. */
KG2 = TRUE;
SetAPen(RP, 1L);
SetBPen(RP, 0L);
SetDrMd(RP, (long)JAM2);
while (KG2 == TRUE)
{
Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
if (Message == 0)
{
CheckMemoryForIRQVirus();
Delay(60);
continue;
};
Class = Message->Class;
Code = Message->Code;
ReplyMsg((struct Message *)Message);
if (Class == CLOSEWINDOW)
{
KG2 = FALSE;
continue;
};
if (Class == MOUSEBUTTONS)
if (Code == MENUDOWN)
{
Class = VANILLAKEY;
Code = 'i';
}
else continue;
if (Class == VANILLAKEY)
{
char flag;
switch (Code)
{
case 'i':
case 'I':
if (WindowBig == TRUE) WindowBig = FALSE;
else WindowBig = TRUE;
if (WindowBig == TRUE)
{
if (Window->TopEdge > (180-WIN_SIZE)) MoveWindow(Window, 0L, (long)-Window->TopEdge);
SizeWindow(Window, 0L, WIN_SIZE);
} else SizeWindow(Window, 0L, -WIN_SIZE);
WaitForNewSize();
break;
case 'c':
case 'C':
for (x=0; x<4; x++) ChangeCount[x] = 10000;
CheckBlock();
default:
flag = ShowAscii(Code);
if (flag == 1) CheckBlock();
};
if (WindowBig == TRUE) DoStats();
};
if (Class == DISKINSERTED)
{
CheckBlock();
if (WindowBig == TRUE) DoStats();
};
};
CloseWindow(Window);
}
/************************************************/
/* Opens trackdisk, finds out who's out there, */
/* and sets Changecount up accordioningly. */
/************************************************/
SetUp()
{
long x;
for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
{
ChangeCount[x] = 1000;
error = OpenDevice(TDName,(long)x,diskreq,0L);
if (error > 0)
{
ChangeCount[x] = -1;
} else CloseDevice(diskreq);
};
}
/*********************************************************/
/* This routine returns which drive changed disks lately */
/*********************************************************/
WhoChanged()
{
char RetVal = -1; /* The value we'll return */
for (x = 0; x < 4; x++)
{
if (ChangeCount[x] == -1)
continue; /* no drive here */
error = OpenDevice(TDName,(long)x,diskreq,(long)0);
if (error > 0)
continue; /* no drive here */
diskreq->io_Command = TD_CHANGESTATE;
DoIO(diskreq);
if (diskreq->io_Actual != 0)
{
CloseDevice(diskreq);
continue;
};
diskreq->io_Command = TD_CHANGENUM;
DoIO(diskreq);
if (diskreq->io_Actual != ChangeCount[x])
{
RetVal = x;
ChangeCount[x] = diskreq->io_Actual;
CloseDevice(diskreq);
break;
};
CloseDevice(diskreq);
};
return(RetVal);
}
/****************************************************************/
/* Figures out which drive changed disks (using WhoChanged(), */
/* And checks it. Calling this after every DISKINSERTED is OK.*/
/****************************************************************/
CheckBlock()
{
/* How many register vars can I use, anyway? */
register long Sum, Virus;
register long a, Unit;
char SCA, ByteWarrior, Revenge, BBandit;
char NorthStar, Obelisk, Pentagon, SystemZ;
register unsigned long *iptr;
unsigned long *ptr;
char drivename[10];
while ((Unit = WhoChanged()) != -1)
{
sprintf(drivename, "DF%c:", Unit+'0');
SCA = FALSE;
BBandit = FALSE;
Revenge = FALSE;
ByteWarrior = FALSE;
NorthStar = FALSE;
Obelisk = FALSE;
Pentagon = FALSE;
SystemZ = FALSE;
/* Unit # to open is returned by "WhoChanged()" up above. */
if (Unit == -1) return;
error = OpenDevice(TDName,(long)Unit,diskreq,0L);
if (error > 0) return;
DisksChecked++;
error = ReadBlock();
CloseDevice(diskreq);
if (error == FALSE) return;
ptr = (long *)diskbuffer;
iptr = (long *)diskbuffer;
if (iptr[0] != ID_DOS_DISK) return; /* No DOS/0 */
Sum = 0;
for (a=0; a<256 /*1024/4 cuz we're dealing with ptr math now*/ ; a++)
{
LastSum = Sum;
Sum = Sum + ptr[a];
if (LastSum > Sum) Sum++; /* took me a while to figger this out */
}
if (Sum != 0)
{
CheckDriveForIRQ(drivename);
return; /* if it's not bootable, we DONT want it! */
};
if (diskbuffer[0x40] == 0xff)
if (diskbuffer[0x41] == 0xa0)
if (diskbuffer[0x42] == 0x20)
if (diskbuffer[0x42] == 0x40)
{
PentagonCount++;
Pentagon = TRUE;
}
if (diskbuffer[0x170] == 0xfe)
if (diskbuffer[0x171] == 0x3a)
if (diskbuffer[0x172] == 0x4c)
if (diskbuffer[0x173] == 0xdf)
{
SystemZCount++;
SystemZ = TRUE;
}
if (diskbuffer[0x34] == 100)
if (diskbuffer[0xc4] == 48)
if (diskbuffer[0xc0] == 68)
if (diskbuffer[0xf1] == 7)
{
ByteWarriorCount++;
ByteWarrior = TRUE;
};
if (diskbuffer[0x2b] == '9')
if (diskbuffer[0x2c] == '.')
if (diskbuffer[0x2d] == '8')
if (diskbuffer[0x2e] == '7')
{
ByteBanditCount++;
BBandit = TRUE; /* 9.87 is part of BBandit Virus */
};
/* check specifically for SCA virus */
if (diskbuffer[8] == 'C')
if (diskbuffer[9] == 'H')
if (diskbuffer[10] == 'W')
{
SCA = TRUE; /* CHW is part of SCA virus */
SCACount++;
};
if (diskbuffer[0xe] == 'I')
if (diskbuffer[0xf] == 'D')
if (diskbuffer[0x10] == '9')
if (diskbuffer[0x1a6] == 'f')
{
Revenge= TRUE;
RevengeCount++;
};
if (diskbuffer[0x12] == 78)
if (diskbuffer[0x13c] == 68)
if (diskbuffer[0x18] == 83)
if (diskbuffer[0x19] == 116)
{
NorthStar = TRUE;
NorthStarCount++;
};
if (diskbuffer[0x38] == 71)
if (diskbuffer[0xbc] == 83)
if (diskbuffer[0x1fb] == 100)
if (diskbuffer[0x2d] == 80)
{
Obelisk = TRUE;
ObeliskCount++;
};
/* compare boot block with real boot block. If it's not, notify God. */
Virus = FALSE;
for (x = 0; x < 39; x++) /* num of bytes in bootblock */
{
if (diskbuffer[8+x] != bootblock[8+x])
{
Virus = TRUE;
};
};
/* Oh no, a Virus! */
if (Virus == TRUE)
{
NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
TEXTPTR[23] = '0'+Unit;
error = FALSE;
if (SCA == TRUE)
{
/* OH NOOOOO, an SCA virus. Wimpo virus, compared to BBandit
but it's a lot nicer code to read. */
error = MyRequest(VN_SCA, 1);
}
else if (BBandit == TRUE)
{
/* The Byte Bandit Virus. Tricky bugger, he WAS. Cheats, tho. */
sprintf(CopyText, copystring, (diskbuffer[74]*256)+diskbuffer[75]);
BuildITBodyText(VN_BYTEBANDIT, 1);
error = AutoRequest(Window, &BBDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
}
else if (Revenge == TRUE)
{
/* Revenge virus. X rated bugger, lot like Byte Bandit. */
sprintf(CopyText, copystring, (diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
BuildITBodyText(VN_REVENGE, 1);
error = AutoRequest(Window, &RevDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
}
else if (ByteWarrior == TRUE)
{
/* Byte Warrior. Very 'friendly' virus. Ez to get rid of. */
error = MyRequest(VN_BYTEWARRIOR, 1);
}
else if (Pentagon == TRUE)
{
/* Pentagon Circle. An 'AntiVirus', and not a bad one at that. */
error = MyRequest(VN_PENTAGON, 1);
}
else if (SystemZ == TRUE)
{
/* SystemZ, Very benign, but it can spread */
error = MyRequest(VN_SYSTEMZ, 1);
}
else if (NorthStar == TRUE)
{
/* NorthStar. Nice virus - alerts you to others, ez to get rid of */
error = MyRequest(VN_NORTHSTAR, 1);
}
else if (Obelisk == TRUE)
{
/* At least these guys are getting creative with their Graphics! */
error = MyRequest(VN_OBELISK, 1);
}
else
{
/* Probably just a custom boot block (or a new virus...) */
error = AutoRequest(Window, &Body1, &SCAPos, &SCANeg, 0L, 0L, 320L, 70L);
}
if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
};
CheckDriveForIRQ(drivename);
}; /* End of While Whochanged */
}
/********************************************/
/* This is where the boot code gets changed */
/********************************************/
DoInstall(un)
int un; /* unit to write to */
{
register int x;
/* Rewrite disk? Really? */
error = AutoRequest(Window, &REWBody, &REWPos, &REWNeg, 0L, 0L, 320L, 75L);
if (error != TRUE) return; /* user changed his brain. */
DisksInstalled++;
error = OpenDevice(TDName, (long)un,diskreq,0L);
if (error > 0) return;
TryGain:
diskreq->io_Command = TD_PROTSTATUS;
DoIO(diskreq); /* check if disk is write protected */
if (diskreq->io_Actual != 0)
{
error = AutoRequest(Window, &ERRBody, &ERRPos, &ERRNeg, 0L, 0L, 280L, 75L);
if (error == TRUE) /* error is true or false, depending on user */
{
goto TryGain;
};
CloseDevice(diskreq);
return; /* unrecoverable write protect error!! Panic!!!!!!! */
};
for (x = 0; x < 1024; x++)
diskbuffer[x] = 0; /* clear diskbuffer to zero. clean. */
CopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
/* Write it ! */
error = 0;
diskreq->io_Length = 1024; /* here we go! */
diskreq->io_Data = (APTR)diskbuffer;
diskreq->io_Command = CMD_WRITE;
diskreq->io_Offset = 0L;
DoIO(diskreq);
error = diskreq->io_Error;
if (error < 19)
{
diskreq->io_Command = CMD_UPDATE; /* flush buffer to disk */
DoIO(diskreq);
error = diskreq->io_Error;
};
if (error < 19)
{
diskreq->io_Length = 0;
diskreq->io_Command = ETD_MOTOR;
DoIO(diskreq); /* turn off motor */
error = diskreq->io_Error;
};
CloseDevice(diskreq);
if (error > 19)
{
SetWindowTitles(Window, "Error, Nothing Done.", (STRPTR)-1);
}
else
{
SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
};
Delay(150L);
SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
}
/************************/
CheckMemoryForViruses()
{
long Temp;
unsigned short *wordpointer;
unsigned long *LongMemPointer; /* Used for reading FROM memory */
unsigned long *ptr;
char linebuffer[80];
char *charpointer;
/**************- Check for Byte Bandit (look at TD Vector) *************/
/* (Byte Bandit isn't at a fixed location. Depends on your RAM. */
/* LongMemPointer = &trackdisk.device */
LongMemPointer = (long *)FindName(&ExecBase->DeviceList, TDName);
Temp = (long)LongMemPointer;
Temp = Temp - 0x1c;
LongMemPointer = (long *)Temp;
VirusBase = (*LongMemPointer) - 0x1b8;
LongMemPointer = (unsigned long *)VirusBase;
if (*LongMemPointer == ID_DOS_DISK) /* klugo */
{
/* Ok, so we don't really remove it from memory, but we DO render
it harmless. */
Disable();
charpointer = (char *)VirusBase;
charpointer[0xaa] = 0x4e;
charpointer[0xac] = 0x4e;
charpointer[0xae] = 0x4e;
charpointer[0xb0] = 0x4e;
charpointer[0xab] = 0x71;
charpointer[0xad] = 0x71;
charpointer[0xaf] = 0x71;
charpointer[0xb1] = 0x71;
charpointer[0x1c2] = 0x60;
charpointer[0x1c3] = 0;
charpointer[0x2d2] = 0x60;
charpointer[0x2d3] = 0;
charpointer[0x388] = 0x4e;
charpointer[0x389] = 0x75;
charpointer[0x3ea] = 0;
charpointer[0x3eb] = 0;
charpointer[0] = 0;
Enable();
MyRequest(VN_BYTEBANDIT, 2);
};
/****************- Look for Revenge Virus (at $7e000) ****************/
if ((unsigned long)ExecBase->CoolCapture == (unsigned long)516192)
{
/* Fix the CoolCapture vector */
ExecBase->CoolCapture = 0;
Disable();
wordpointer = (unsigned short *)(0x7e000);
wordpointer[0] = 0;
wordpointer = (unsigned short *)(0x7e000+0x1e0);
wordpointer[0] = 0x4ef9;
wordpointer[1] = 0x0007;
wordpointer[2] = 0xe066;
wordpointer = (unsigned short *)0x7e2da;
wordpointer[0] = 0x4ef9;
wordpointer[1] = 0x0007;
wordpointer[2] = 0xe06c;
Enable();
MyRequest(VN_REVENGE, 2);
};
/******************** See if SCA is in RAM ***************************/
if ((long)ExecBase->CoolCapture == (long)0x7ec3e)
{
ExecBase->CoolCapture = 0;
MyRequest(VN_SCA, 2);
};
/***************** Check for Obelisk *******************************/
if ((APTR)ExecBase->CoolCapture == (APTR)0x7e86c)
{
ExecBase->CoolCapture = 0;
ptr = (unsigned long *)0x7e88a;
Forbid();
ptr[0] = 10;
Permit();
MyRequest(VN_OBELISK, 2);
};
/******************** How about North Star? **************************/
if ((APTR)ExecBase->CoolCapture == (APTR)0x7ec0e)
{
ExecBase->CoolCapture = 0;
MyRequest(VN_NORTHSTAR, 2);
};
/********************* Check for Byte Warrior ************************/
wordpointer = (unsigned short *)0x7f800;
if ( wordpointer[0] == (0x444f) )
{
wordpointer = (unsigned short *)0x7f954;
if (wordpointer[0] == 0x4afc)
{
wordpointer[0] = 0; /* Kill resident matchtag */
Forbid();
wordpointer = (unsigned short *)0x7f972;
wordpointer[0] = 0x4ef9;
wordpointer[1] = 0x00fc;
wordpointer[2] = 0x06dc;
wordpointer = (unsigned short *)0x7f800;
wordpointer[0] = 0;
Permit();
MyRequest(VN_BYTEWARRIOR, 2);
};
};
/******************** See if Pentagon is in RAM ***************************/
if ((long)ExecBase->CoolCapture == (long)0x7fb4c)
{
ExecBase->CoolCapture = 0;
/* He sometimes has the DoIO() setfunctioned, I can't figure out
when, but even if he does, he doesn't do any harm anyway, and
with CoolCapture set to 0, he'll be gone at next reboot. */
MyRequest(VN_PENTAGON, 2);
};
/********************* Check for Byte Warrior ************************/
wordpointer = (unsigned short *)0x7f4e0;
if ( wordpointer[0] == (0x4afc) )
{
if (wordpointer[1] == 0x0007)
{
wordpointer[0] = 0;
MyRequest(VN_SYSTEMZ, 2);
};
}
if (ExecBase->CoolCapture != 0)
{
sprintf(linebuffer, "Cool%s%x", CaptureStr, ExecBase->CoolCapture);
if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0;
}
if (ExecBase->ColdCapture != 0)
{
sprintf(linebuffer, "Cold%s%x", CaptureStr, ExecBase->ColdCapture);
if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0;
}
if (ExecBase->WarmCapture != 0)
{
sprintf(linebuffer, "Warm%s%x", CaptureStr, ExecBase->WarmCapture);
if (MyRequest(linebuffer, 3) == TRUE) ExecBase->WarmCapture = 0;
}
}
/**************************************************************/
/* This is the routine that displauys a block as ASCII text. */
/**************************************************************/
ShowAscii(key)
long key;
{
int drive;
int x,y;
int deltax, deltay;
long a;
int FLAG=0;
struct RastPort *RP;
RP = Window->RPort;
drive = key - '0';
if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
error = OpenDevice(TDName,(long)drive,diskreq,0L);
if (error > 0) return;
error = ReadBlock();
CloseDevice(diskreq);
if (error == FALSE) return;
/* save the amount we moved the window */
deltax = Window->LeftEdge;
deltay = Window->TopEdge;
MoveWindow(Window, -deltax, -deltay);
if (WindowBig == FALSE) SizeWindow(Window, 278L, 160L);
else SizeWindow(Window, 278L, 60L);
WaitForNewSize();
SetAPen(RP, 3L);
Move(RP, (long)(14+(12*8)), 165L);
Text(RP, "Block 0", 7L);
Move(RP, (long)(324+(12*8)), 165L);
Text(RP, "Block 1", 7L);
SetAPen(RP, 1L);
text[2] = key;
SetWindowTitles(Window, text, (STRPTR)-1);
x=0; y=0;
SetAPen(RP, 1L);
SetDrMd(RP, JAM2);
for (a=0; a<512; a=a+32)
{
Move(RP, (long)(10+(x*8)), (long)20+(y*9));
Text(RP, &diskbuffer[a], 32L);
Move(RP, (long)(320+(x*8)), (long)20+(y*9));
Text(RP, &diskbuffer[a+512], 32L);
y++;
};
Wait(1<<Window->UserPort->mp_SigBit);
Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
/* If a disk was inserted, we want CheckBlock() to happen later on some time */
if (Message->Class == DISKINSERTED) FLAG=1;
ReplyMsg((struct Message *)Message);
if (WindowBig == FALSE)
SizeWindow(Window, -278L, -160L);
else SizeWindow(Window, -278L, -60L);
SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
WaitForNewSize();
/* deltas plus current position, in case dude moved the window */
MoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
Delay(2L);
return(FLAG);
}
/*
When you do a SizeWindow() command, you have to wait for a NEWSIZE
IntuiMessage before drawing in it. That's all this routine does.
*/
WaitForNewSize()
{
while (TRUE)
{
WaitPort(Window->UserPort);
Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
if (Message->Class != NEWSIZE)
{
ReplyMsg((struct Message *)Message);
continue;
};
ReplyMsg((struct Message *)Message);
break;
};
}
/*
type:
1 == "is infected with the xxxx VIRUS!"
2 == "somethin about virus in ram"
3 == virus in cold/cool/warm capture
*/
BuildITBodyText(text, type)
char *text;
int type;
{
switch (type)
{
case 1:
strcpy(ITBodyText, "infected with the `");
strcat(ITBodyText, text);
strcat(ITBodyText, "' VIRUS!");
break;
case 2:
strcpy(ITBodyText, "NOTICE: The `");
strcat(ITBodyText, text);
strcat(ITBodyText, "' VIRUS was found");
break;
};
}
/***** an attempt to save space *********/
MyRequest(string, type)
char *string;
int type;
{
if (type != 3)
{
BuildITBodyText(string, type);
} else
{
Mem1.IText = string;
};
if (type == 1) return(AutoRequest(Window, &GenericDiskBody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L));
if (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 395L, 78L));
if (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 395L, 78L));
}
/********* DoStats() **********/
DoStats()
{
char linebuffer[80];
SetAPen(RP, 0L);
RectFill(RP, 2L, 11L, 303L, (WIN_SIZE + 7));
SetAPen(RP, 1L);
sprintf(linebuffer, " Disks Checked: %d", DisksChecked);
Out(20, linebuffer);
sprintf(linebuffer, "Disks Installed: %d", DisksInstalled);
Out(29, linebuffer);
Out(43, " Viruses Found:");
PV(52, VN_SCA, SCACount);
PV(61, VN_BYTEBANDIT, ByteBanditCount);
PV(70, VN_NORTHSTAR, NorthStarCount);
PV(79, VN_BYTEWARRIOR, ByteWarriorCount);
PV(88, VN_REVENGE, RevengeCount);
PV(97, VN_OBELISK, ObeliskCount);
PV(106, VN_IRQ, IRQFound);
PV(115, VN_PENTAGON, PentagonCount);
PV(124, VN_SYSTEMZ, SystemZCount);
}
/****************** Ok, we're REALLY being chintzy here. */
PV(num, name, howmany)
int num;
char *name;
int howmany;
{
char linebuffer[80];
sprintf(linebuffer, "%-16s: %d", name, howmany);
Out(num, linebuffer);
}
/***************************************** Cheap? Me? Nooooo.... */
/* This will write text to the column number in NUM, the text in Name. */
/* Or something like that. ********************************************/
Out(num, name)
int num;
char *name;
{
int len;
len = 0;
while (name[len] != 0) len++;
Move(RP, 20L, (long)num);
Text(RP, name, len);
}
ReadBlock()
{
diskreq->io_Command = CMD_READ;
diskreq->io_Data = (APTR)diskbuffer;
diskreq->io_Length = 3*512;
diskreq->io_Offset = 0;
DoIO(diskreq);
if (diskreq->io_Error > 0) return(FALSE);
diskreq->io_Length = 0;
diskreq->io_Command = TD_MOTOR;
DoIO(diskreq);
return(TRUE);
}
unsigned long *OpenLibVectorPtr;
unsigned long *EntryForOldOpenLib;
unsigned long *OldOldOpenLibVector;
CheckMemoryForIRQVirus()
{
long *Array;
int Num;
Array = (long *)4;
Array = (long *)Array[0];
Num = (int)Array;
Num = Num - 0x196;
OpenLibVectorPtr = (unsigned long *)Num;
EntryForOldOpenLib = (unsigned long *)OpenLibVectorPtr[0];
OldOldOpenLibVector = (unsigned long *)(((char *)EntryForOldOpenLib) + 0x12);
if (EntryForOldOpenLib[0] == 0x2f3a0010)
{
/*
printf("Setting $%x to $%x\n", OpenLibVectorPtr, OldOldOpenLibVector[0]);
*/
OpenLibVectorPtr[0] = OldOldOpenLibVector[0];
ExecBase->KickTagPtr = 0;
MyRequest(VN_IRQ, 2);
};
}
/********************************/
CheckDriveForIRQ(drivename)
char *drivename;
{
int err;
char buffer[80];
char dirbuffer[80];
char filebuffer[100];
char tempbuffer[100];
char FoundInDir;
char FoundInFname;
char chr;
int index;
char pass;
FoundInDir = FALSE;
FoundInFname = FALSE;
filebuffer[0] = 0;
pass = 0;
sprintf(dirbuffer, "%sC/DIR", drivename);
err = CheckFileForIRQ(dirbuffer,0);
if (err == 1)
{
IRQFound++;
FoundInDir = TRUE;
}
else dirbuffer[0] = 0;
index = 0;
sprintf(tempbuffer, "%ss/Startup-Sequence", drivename);
fp = Open(tempbuffer, MODE_OLDFILE);
if (fp == 0)
filebuffer[0] = 0;
else
{
while (TRUE)
{
err = Read(fp, &chr, 1);
if (err == 0) break;
if (chr == 34) continue;
if (chr == 0x0a) continue;
if (chr == ';') continue;
if (chr == ' ') continue;
break;
};
if (err != 0)
{
while (TRUE)
{
filebuffer[index++] = chr;
filebuffer[index] = 0;
err = Read(fp, &chr, 1);
if (err == 0) break;
if (chr == 34) break;
if (chr == 0x0a) break;
if (chr == ';') break;
if (chr == 32) break;
};
};
Close(fp);
sprintf(buffer, "%s%s", drivename, filebuffer);
err = CheckFileForIRQ(buffer, 0);
if (err == -1)
{
sprintf(buffer, "C:%s", filebuffer);
err = CheckFileForIRQ(buffer, 0);
};
strcpy(filebuffer, buffer);
if (err == 1)
{
FoundInFname = TRUE;
IRQFound++;
}
else filebuffer[0] = 0;
};
if (FoundInDir == FALSE && FoundInFname == FALSE) return(0);
WBenchToFront();
fp = Open("CON:70/20/500/100/VirusX", MODE_NEWFILE);
if (fp == 0) return(0);
WriteFP(fp, "
NOTICE
: The
IRQ
Virus was found on volume ");
WriteFP(fp, drivename);
WriteFP(fp, "\n");
while (TRUE)
{
if (pass == 0)
{
strcpy(tempbuffer, dirbuffer);
}
else if (pass == 1)
{
strcpy(tempbuffer, filebuffer);
}
else if (pass == 2) break;
pass++;
if (tempbuffer[0] == 0) continue;
sprintf(buffer, "\nIn the command: %s\n", tempbuffer);
WriteFP(fp, buffer);
WriteFP(fp, "Okay to remove it? [Y]: ");
Read(fp, buffer, 3);
if (toupper(buffer[0]) == 'Y')
{
err = CheckFileForIRQ(tempbuffer, 1);
if (err == 1)
{
WriteFP(fp, "Virus removed.\n");
} else
{
sprintf(buffer, "Error #%d removing virus. Check file.\n", err);
WriteFP(fp, buffer);
}
};
};
WriteFP(fp, "\nHit
RETURN
to continue...");
Read(fp, buffer, 3);
Close(fp);
}
WriteFP(fp, string)
int fp;
char *string;
{
Write(fp, string, strlen(string));
}
/********************************/
#define VTAG 0x00000109L
#define BEGIN OFFSET_BEGINNING
#define END OFFSET_END
#define OLD MODE_OLDFILE
#define NEW MODE_NEWFILE
#define SLONG ((long)sizeof(long))
#define OK 1 /* no error */
#define NOFILE -1 /* can't find file */
#define SEEKERR -2 /* seek error on file */
#define ALLOCERR -3 /* can't allocate memory */
#define READERR -4 /* error reading file */
#define VIRUSNF -5 /* virus not found in file */
#define WRITERR -6 /* error writing to file */
#define OPENERR -7 /* error opening file for write */
#define NOTEXE -8 /* not an executable file */
#define GOTHIM OK /* removed virus from file */
#define VTAG 0x00000109L /* virus hunk length */
#define VSIG1 0x0000FFFEL /* part of virus signature */
#define VSIG2 0x61000000L /* part of virus signature */
static long inp, *buff, size;
cleanup(val)
int val;
{
if(inp) Close(inp);
if(buff) FreeMem(buff,size);
return val;
}
CheckFileForIRQ(fname, flag)
char *fname;
int flag;
{
int i = 0;
long fhunk, lhunk, nhunk;
long tbuff[488/4];
inp = 0L; buff = 0L;
if((inp = Open(fname,OLD)) == 0) /* open the desired file */
return NOFILE;
Read(inp,(char *)&tbuff[0],487); /* get the first long word */
if(tbuff[0] != 0x000003F3) /* check for executable file */
return cleanup(NOTEXE);
if(tbuff[5] != VTAG)
return cleanup(VIRUSNF);
Seek(inp,0L,END); /* seek to end of file */
size = Seek(inp,0L,BEGIN); /* rewind the file to get size */
if(size <= 0L)
return cleanup(SEEKERR);
if((buff = AllocMem(size,0L)) == 0) /* mem buffer for file */
return cleanup(ALLOCERR);
if(Read(inp,(char *)&buff[0],size) != size) /* read entire file into buffer */
return cleanup(READERR);
nhunk = buff[ 2 ]; /* number of hunks in file */
fhunk = buff[ 3 ]; /* first hunk */
lhunk = buff[ 4 ]; /* last hunk */
/*
the IRQ virus inserts his code as the first hunk in the file
we can find the first hunk in the 6th longword of the file
*/
/* find the start of the virus hunk */
while(buff[ i++ ] != 0x000003E9)
;
/*
The virus checks the first hunk for it's signature to prevent
reinfecting an already infected program. It actually checks for
0xFFFE6100 which is the lower half of a move.m instruction and
the upper half of a bsr instruction. Here we do the same.
i points to the virus code hunk length.
*/
if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
|| ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
return cleanup(VIRUSNF);
if (flag == 0)
return cleanup(1);
/*
close the file and reopen it with write access
mode NEW will effectivly delete the old file contents so if a
file error occurs before we finish, the file will be corrupt
*/
Close(inp);
if((inp = Open(fname,NEW)) == 0)
return cleanup(OPENERR);
buff[2] -= 1; buff[4] -= 1; /* readjust program header info */
/* write new header */
if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
return cleanup(WRITERR);
if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
return cleanup(WRITERR);
/*
subtract length of virus hunk and overhead from file size
i was calculated earlier
*/
i = i + 8L + VTAG;
size = (size/SLONG - i)*SLONG;
/* and write old code out to file, ignoring virus hunk */
if(Write(inp,(char *)&buff[i],size) != size)
return cleanup(WRITERR);
/* we're done, the file is clean and intact */
return cleanup(GOTHIM);
}